using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

namespace SCore.UI
{
    public class JoyStick : MonoBehaviour, IPointerUpHandler, IPointerDownHandler, IDragHandler
    {
        [SerializeField] private GameObject _joyMask;
        [SerializeField] private RectTransform _joystickBackground;
        [SerializeField] private RectTransform _joyStick;
        [SerializeField] private RectTransform _joyStickArrow;
        [Range(0, 10f)] [SerializeField] private float _joystickMovementRange = 1f;
        [SerializeField] private Camera _uiCamera;

        private Vector2 _joyStickInput = Vector2.zero;
        private Vector2 _joystickCurrentPosition = new Vector2(0, 0);
        [SerializeField] private Color _normalColor = Color.white;
        [SerializeField] private Color _pressedColor = Color.white;
        [SerializeField] private State _joystickState;
        [SerializeField] private ShowState _joystickShowState;


        /*List of events*/
        public UnityEvent OnGameStart;
        public UnityEvent OnPressedJoystick;
        public UnityEvent OnStartedDraggingJoystick;
        public UnityEvent OnStoppedDraggingJoystick;
        public UnityEvent<Vector2> OnDragJoystick;

        private void Start()
        {
            OnGameStart.Invoke();
            SetJoystickColor(_normalColor);
            if (_joystickShowState == ShowState.Dynamic)
            {
                _joystickBackground.gameObject.SetActive(false);
            }
        }

        public void OnPointerDown(PointerEventData eventdata)
        {
            if (_joystickState == State.Un_Interactable)
            {
                return;
            }

            if (_joystickShowState == ShowState.Dynamic)
            {
                _joystickBackground.gameObject.SetActive(true);
            }

            SetJoystickColor(_pressedColor);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                GetComponent<RectTransform>(),
                eventdata.position,
                _uiCamera,
                out _joystickCurrentPosition
            );
            _joystickBackground.localPosition = _joystickCurrentPosition;
            _joyStick.anchoredPosition = Vector2.zero;
            OnPressedJoystick.Invoke();
        }

        public void OnPointerUp(PointerEventData eventdata)
        {
            if (_joystickState == State.Un_Interactable)
            {
                return;
            }

            if (_joystickShowState == ShowState.Dynamic)
            {
                _joystickBackground.gameObject.SetActive(false);
            }

            SetJoystickColor(_normalColor);

            _joyStickInput = new Vector2(0, 0);
            _joyStick.anchoredPosition = new Vector2(0, 0);
            OnStoppedDraggingJoystick.Invoke();
            OnDragJoystick?.Invoke(_joyStickInput);
        }

        public void OnDrag(PointerEventData eventdata)
        {
            if (_joystickState == State.Un_Interactable)
            {
                return;
            }

            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                GetComponent<RectTransform>(),
                eventdata.position,
                _uiCamera,
                out Vector2 dragLocalPosition
            );
            Vector2 direction = dragLocalPosition - _joystickCurrentPosition;
            if (direction.magnitude > _joystickBackground.sizeDelta.x / 2f)
            {
                _joyStickInput = direction.normalized;
            }
            else
            {
                _joyStickInput = direction / (_joystickBackground.sizeDelta.x / 2f);
            }

            _joyStick.anchoredPosition =
                (_joyStickInput * _joystickBackground.sizeDelta.x / 2f) * _joystickMovementRange;
            float angle = Mathf.Atan2(_joyStickInput.y, _joyStickInput.x) * Mathf.Rad2Deg;
            if (angle < 0)
            {
                angle += 360f; // 将负角度转换为正角度
            }

            _joyStickArrow.rotation = Quaternion.Euler(0, 0, angle);
            OnStartedDraggingJoystick.Invoke();
            OnDragJoystick?.Invoke(_joyStickInput);
        }

        private void SetJoystickColor(Color color)
        {
            _joystickBackground.gameObject.GetComponent<Image>().color = color;
            _joyStick.gameObject.GetComponent<Image>().color = color;
        }

        public float GetVerticalValue()
        {
            return _joyStickInput.y;
        }

        public float GetHorizontalValue()
        {
            return _joyStickInput.x;
        }

        public Vector2 GetHorizontalAndVerticalValue()
        {
            return _joyStickInput;
        }

        public void SetState(State state)
        {
            _joystickState = state;
        }

        public State GetState()
        {
            return _joystickState;
        }

        public void SetMask(bool mask)
        {
            _joyMask.SetActive(mask);
        }
    }

    public enum State
    {
        Interactable,
        Un_Interactable
    }

    public enum ShowState
    {
        Dynamic,
        Normal
    }
}